#!/usr/bin/env node
/**
 * Phase3 三层对齐验证生成器
 * 用法：node scripts/phase3/generate-three-layer-validation.js ComponentName
 *
 * 验证 Preview ↔ FieldNode ↔ EditFields 三层一致性
 * 实施分析报告建议2: 三层对齐验证
 */

const fs = require('fs');
const path = require('path');
const ts = require('typescript');

/**
 * 从 preview-props-schema.json 提取字段
 */
function extractPreviewSchema(componentName, root) {
  const schemaPath = path.join(root, componentName, 'phase2/preview-props-schema.json');
  if (!fs.existsSync(schemaPath)) {
    throw new Error(`preview-props-schema.json 不存在: ${schemaPath}`);
  }

  const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
  const fields = {};

  if (schema.props) {
    Object.entries(schema.props).forEach(([field, def]) => {
      fields[field] = {
        type: def.type || 'string',
        default: def.default
      };
    });
  }

  return { fields, count: Object.keys(fields).length };
}

/**
 * 从 fields/aiComponents.ts 提取 FieldNode
 */
function extractFieldNode(componentName, root) {
  const fieldsPath = path.join(root, 'src/components/editor/schema/fields/aiComponents.ts');
  if (!fs.existsSync(fieldsPath)) {
    throw new Error(`fields/aiComponents.ts 不存在: ${fieldsPath}`);
  }

  const source = fs.readFileSync(fieldsPath, 'utf8');
  const sourceFile = ts.createSourceFile('aiComponents.ts', source, ts.ScriptTarget.Latest, true);

  let fieldNodeProps = null;

  function visit(node) {
    // 查找 componentCode === componentName 的配置对象
    if (ts.isObjectLiteralExpression(node)) {
      const typeProperty = node.properties.find(
        p => ts.isPropertyAssignment(p) &&
             p.name.getText(sourceFile) === 'type' &&
             p.initializer.getText(sourceFile).replace(/['"]/g, '') === componentName
      );

      if (typeProperty) {
        const propsProperty = node.properties.find(
          p => ts.isPropertyAssignment(p) && p.name.getText(sourceFile) === 'props'
        );

        if (propsProperty && ts.isObjectLiteralExpression(propsProperty.initializer)) {
          const props = {};
          propsProperty.initializer.properties.forEach(prop => {
            if (ts.isPropertyAssignment(prop)) {
              const propName = prop.name.getText(sourceFile);
              props[propName] = {
                value: prop.initializer.getText(sourceFile)
              };
            }
          });
          fieldNodeProps = props;
        }
      }
    }

    ts.forEachChild(node, visit);
  }

  visit(sourceFile);

  if (!fieldNodeProps) {
    throw new Error(`FieldNode for ${componentName} 未找到`);
  }

  return { fields: fieldNodeProps, count: Object.keys(fieldNodeProps).length };
}

/**
 * 从 edit/aiComponents.ts 提取 EditFields
 */
function extractEditFields(componentName, root) {
  const editPath = path.join(root, 'src/components/editor/schema/edit/aiComponents.ts');
  if (!fs.existsSync(editPath)) {
    throw new Error(`edit/aiComponents.ts 不存在: ${editPath}`);
  }

  const source = fs.readFileSync(editPath, 'utf8');
  const sourceFile = ts.createSourceFile('aiComponents.ts', source, ts.ScriptTarget.Latest, true);

  let editFieldsArray = null;

  function visit(node) {
    // 查找 componentCode === componentName 的配置
    if (ts.isObjectLiteralExpression(node)) {
      const componentProperty = node.properties.find(
        p => ts.isPropertyAssignment(p) &&
             p.name.getText(sourceFile) === 'componentCode' &&
             p.initializer.getText(sourceFile).replace(/['"]/g, '') === componentName
      );

      if (componentProperty) {
        const fieldsProperty = node.properties.find(
          p => ts.isPropertyAssignment(p) && p.name.getText(sourceFile) === 'fields'
        );

        if (fieldsProperty && ts.isArrayLiteralExpression(fieldsProperty.initializer)) {
          const fields = [];
          fieldsProperty.initializer.elements.forEach(element => {
            if (ts.isObjectLiteralExpression(element)) {
              const fieldObj = {};
              element.properties.forEach(prop => {
                if (ts.isPropertyAssignment(prop)) {
                  const key = prop.name.getText(sourceFile);
                  fieldObj[key] = prop.initializer.getText(sourceFile).replace(/['"]/g, '');
                }
              });
              fields.push(fieldObj);
            }
          });
          editFieldsArray = fields;
        }
      }
    }

    ts.forEachChild(node, visit);
  }

  visit(sourceFile);

  if (!editFieldsArray) {
    throw new Error(`EditFields for ${componentName} 未找到`);
  }

  const fieldMap = {};
  editFieldsArray.forEach(field => {
    if (field.name) {
      fieldMap[field.name] = {
        belongTo: field.belongTo,
        type: field.type
      };
    }
  });

  return { fields: fieldMap, count: Object.keys(fieldMap).length };
}

/**
 * 生成三层验证报告
 */
function generateThreeLayerValidation(componentName) {
  const root = process.cwd();

  console.log(`\n📋 Phase3 三层对齐验证`);
  console.log(`  组件: ${componentName}`);

  // 提取三层数据
  const preview = extractPreviewSchema(componentName, root);
  const fieldNode = extractFieldNode(componentName, root);
  const editFields = extractEditFields(componentName, root);

  console.log(`  Preview字段: ${preview.count}`);
  console.log(`  FieldNode字段: ${fieldNode.count}`);
  console.log(`  EditFields字段: ${editFields.count}`);

  // 验证 FieldNode ↔ Preview
  const fieldToSchemaAligned = [];
  const fieldToSchemaMissing = [];
  const fieldToSchemaExtra = [];

  Object.keys(fieldNode.fields).forEach(field => {
    if (preview.fields[field]) {
      fieldToSchemaAligned.push(field);
    } else {
      fieldToSchemaExtra.push({
        field,
        issue: 'FieldNode存在但Preview缺失'
      });
    }
  });

  Object.keys(preview.fields).forEach(field => {
    if (!fieldNode.fields[field]) {
      fieldToSchemaMissing.push({
        field,
        issue: 'Preview存在但FieldNode缺失'
      });
    }
  });

  // 验证 EditFields ↔ FieldNode
  const editToFieldAligned = [];
  const editToFieldMissing = [];
  const editToFieldExtra = [];

  Object.keys(editFields.fields).forEach(field => {
    if (fieldNode.fields[field]) {
      editToFieldAligned.push(field);
    } else {
      editToFieldExtra.push({
        field,
        issue: 'EditFields存在但FieldNode缺失'
      });
    }
  });

  Object.keys(fieldNode.fields).forEach(field => {
    if (!editFields.fields[field]) {
      editToFieldMissing.push({
        field,
        issue: 'FieldNode存在但EditFields缺失'
      });
    }
  });

  // 验证 Preview ↔ EditFields
  const previewToEditAligned = [];
  const previewToEditMissing = [];
  const previewToEditExtra = [];

  Object.keys(preview.fields).forEach(field => {
    if (editFields.fields[field]) {
      previewToEditAligned.push(field);
    } else {
      previewToEditMissing.push({
        field,
        issue: 'Preview存在但EditFields缺失'
      });
    }
  });

  Object.keys(editFields.fields).forEach(field => {
    if (!preview.fields[field]) {
      previewToEditExtra.push({
        field,
        issue: 'EditFields存在但Preview缺失'
      });
    }
  });

  // 收集错误
  const errors = [
    ...fieldToSchemaMissing,
    ...fieldToSchemaExtra,
    ...editToFieldMissing,
    ...editToFieldExtra,
    ...previewToEditMissing,
    ...previewToEditExtra
  ];

  const warnings = [];
  if (preview.count !== fieldNode.count) {
    warnings.push({
      type: 'count_mismatch',
      message: `Preview(${preview.count}) 与 FieldNode(${fieldNode.count}) 字段数量不一致`
    });
  }
  if (fieldNode.count !== editFields.count) {
    warnings.push({
      type: 'count_mismatch',
      message: `FieldNode(${fieldNode.count}) 与 EditFields(${editFields.count}) 字段数量不一致`
    });
  }

  // 生成报告
  const report = {
    timestamp: new Date().toISOString(),
    componentName,
    layers: {
      preview: `${componentName}/phase2/preview-props-schema.json`,
      fieldNode: 'src/components/editor/schema/fields/aiComponents.ts',
      editFields: 'src/components/editor/schema/edit/aiComponents.ts'
    },
    validation: {
      fieldToSchema: {
        aligned: fieldToSchemaAligned.length,
        missing: fieldToSchemaMissing.length,
        extra: fieldToSchemaExtra.length,
        alignmentRate: preview.count > 0 ? fieldToSchemaAligned.length / preview.count : 0,
        details: {
          aligned: fieldToSchemaAligned,
          missing: fieldToSchemaMissing,
          extra: fieldToSchemaExtra
        }
      },
      editToField: {
        aligned: editToFieldAligned.length,
        missing: editToFieldMissing.length,
        extra: editToFieldExtra.length,
        alignmentRate: fieldNode.count > 0 ? editToFieldAligned.length / fieldNode.count : 0,
        details: {
          aligned: editToFieldAligned,
          missing: editToFieldMissing,
          extra: editToFieldExtra
        }
      },
      previewToEdit: {
        aligned: previewToEditAligned.length,
        missing: previewToEditMissing.length,
        extra: previewToEditExtra.length,
        alignmentRate: preview.count > 0 ? previewToEditAligned.length / preview.count : 0,
        details: {
          aligned: previewToEditAligned,
          missing: previewToEditMissing,
          extra: previewToEditExtra
        }
      }
    },
    errors,
    warnings,
    summary: {
      totalLayers: 3,
      previewFields: preview.count,
      fieldNodeFields: fieldNode.count,
      editFieldsFields: editFields.count,
      fullyAligned: errors.length === 0,
      overallAlignmentRate: (
        (fieldToSchemaAligned.length + editToFieldAligned.length + previewToEditAligned.length) /
        (preview.count + fieldNode.count + editFields.count)
      )
    }
  };

  // 保存到 phase3 目录
  const outputDir = path.join(root, componentName, 'phase3');
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
  }

  const outputFile = path.join(outputDir, 'three-layer-validation.json');
  fs.writeFileSync(outputFile, JSON.stringify(report, null, 2));

  console.log(`\n✅ 三层验证报告已生成: ${outputFile}`);
  console.log(`\n📊 验证结果:`);
  console.log(`  Preview ↔ FieldNode: ${fieldToSchemaAligned.length}/${preview.count} 对齐 (${(report.validation.fieldToSchema.alignmentRate * 100).toFixed(1)}%)`);
  console.log(`  FieldNode ↔ EditFields: ${editToFieldAligned.length}/${fieldNode.count} 对齐 (${(report.validation.editToField.alignmentRate * 100).toFixed(1)}%)`);
  console.log(`  Preview ↔ EditFields: ${previewToEditAligned.length}/${preview.count} 对齐 (${(report.validation.previewToEdit.alignmentRate * 100).toFixed(1)}%)`);

  if (errors.length > 0) {
    console.log(`\n❌ 错误 (${errors.length}):`);
    errors.slice(0, 5).forEach(e => console.log(`  - ${e.field || 'unknown'}: ${e.issue}`));
    if (errors.length > 5) {
      console.log(`  ... 还有 ${errors.length - 5} 个错误`);
    }
    console.log(`\n⚠️  三层对齐验证失败，阻断Phase3完成`);
    process.exit(1);
  }

  if (warnings.length > 0) {
    console.log(`\n⚠️  警告 (${warnings.length}):`);
    warnings.forEach(w => console.log(`  - ${w.message}`));
  }

  console.log(`\n✅ 三层对齐验证通过`);
  return report;
}

// CLI 执行
function main() {
  const componentName = process.argv[2];

  if (!componentName) {
    console.error('❌ 缺少组件名称');
    console.error('用法: node scripts/phase3/generate-three-layer-validation.js ComponentName');
    process.exit(1);
  }

  try {
    generateThreeLayerValidation(componentName);
  } catch (error) {
    console.error(`\n❌ 生成三层验证失败: ${error.message}`);
    console.error(error.stack);
    process.exit(1);
  }
}

main();
